<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Benchmark Presets</title>
    <style>
        body{
            font-family: sans-serif;
        }
        table td{
            padding: 1em 2em;
        }
        button{
            padding: 5px 10px;
        }
    </style>
</head>
<body>
<h2>Document Index Benchmark Comparison</h2>
<h4>Indexed Text: Movie Documents</h4>
<hr>
<div id="container"></div>
<hr>
<script src="../dist/flexsearch.min.js"></script>
<script src="../data/movies.js"></script>
<script>

    (function(){

        var index = {};
        var index_doc = {};
        var flexsearch_doc;
        var flexsearch_doc_field;
        var flexsearch_where;
        var flexsearch_where_custom;
        var flexsearch_tag;
        var flexsearch_static;
        var flexsearch_static_tag;
        var flexsearch_static_tag_query;
        var flexsearch_static_query;
        var flexsearch_index_tag;
        var flexsearch_index_ref;
        var flexsearch_find;

        function add(id, cat, content){
            (index[cat] || (
                index[cat] = new FlexSearch("fast")
            )).add(id, content);
        }

        function search(cat, query){
            return index[cat].search(query);
        }

        function add_doc(cat, content){
            (index_doc[cat] || (
                index_doc[cat] = new FlexSearch({
                    preset: "fast",
                    doc: {
                        id: "id",
                        field: "title"
                    }
                })
            )).add(content);
        }

        function search_doc(cat, query){
            return index_doc[cat].search(query, {
                field: "title"
            });
        }

        var tests = {

            "helper-no-doc": {

                init: function(){},
                add: function(content){

                    add(content.id, content.genre, content.title);
                },
                query: function(query){

                    return search("Adventure", query);
                },
                loops: 400000
            },

            "helper-doc": {

                init: function(){},
                add: function(content){

                    add_doc(content.genre, content);
                },
                query: function(query){

                    return search_doc("Adventure", query);
                },
                loops: 300000
            },

            "doc-no-cat-no-field": {

                init: function(){

                    flexsearch_doc = new FlexSearch({
                        preset: "fast",
                        doc: {
                            id: "id",
                            field: "title"
                        }
                    });
                },
                add: function(content){

                    flexsearch_doc.add(content);
                },
                query: function(query){

                    return flexsearch_doc.search(query);
                },
                loops: 250000
            },

            "doc-no-cat-field": {

                init: function(){

                    flexsearch_doc_field = new FlexSearch({
                        preset: "fast",
                        doc: {
                            id: "id",
                            field: "title"
                        }
                    });
                },
                add: function(content){

                    flexsearch_doc_field.add(content);
                },
                query: function(query){

                    return flexsearch_doc_field.search(query, {
                        field: "title"
                    });
                },
                loops: 250000
            },

            "where-cat": {

                init: function(){

                    flexsearch_where = new FlexSearch({
                        preset: "fast",
                        doc:{
                            id: "id",
                            field: "title"
                        }
                    });
                },
                add: function(content){

                    flexsearch_where.add(content);
                },
                query: function(query){

                    return flexsearch_where.search(query, {
                        field: "title",
                        where: {
                            genre: "Adventure"
                        }
                    });
                },
                loops: 250000
            },

            "where-custom": {

                init: function(){

                    flexsearch_where_custom = new FlexSearch({
                        preset: "fast",
                        doc:{
                            id: "id",
                            field: "title"
                        }
                    });
                },
                add: function(content){

                    flexsearch_where_custom.add(content);
                },
                query: function(query){

                    return flexsearch_where_custom.search(query, {
                        field: "title",
                        where: function(val){
                            return val.genre === "Adventure";
                        }
                    });
                },
                loops: 250000
            },

            "where-tag": {

                init: function(){

                    flexsearch_tag = new FlexSearch({
                        preset: "fast",
                        doc:{
                            id: "id",
                            field: ["title"],
                            tag: ["genre"]
                        }
                    });
                },
                add: function(content){

                    flexsearch_tag.add(content);
                },
                query: function(query){

                    return flexsearch_tag.search(query, {
                        field: "title",
                        where: {
                            genre: "Adventure"
                        }
                    });
                },
                loops: 250000
            },

            "where-indexed-manual": {

                init: function(){

                    flexsearch_index_ref = new FlexSearch({
                        encode: false,
                        tokenize: function(doc){
                            return [doc];
                        },
                        doc:{
                            id: "id",
                            field: ["genre"]
                        }
                    });
                },
                add: function(content){

                    flexsearch_index_ref.add(content);
                },
                query: function(query){

                    return flexsearch_index_ref.search("Adventure", {

                        field: "genre"
                    });
                },
                loops: 300000
            },

            /*
            "where-indexed-tag": {

                init: function(){

                    flexsearch_index_tag = new FlexSearch({
                        preset: "fastest",
                        doc:{
                            id: "id",
                            field: ["title"],
                            tag: ["genre"]
                        }
                    });
                },
                add: function(content){

                    flexsearch_index_tag.add(content);
                },
                query: function(query){

                    return flexsearch_index_tag.search("Adventure", {

                        field: "genre"
                    });
                },
                loops: 250000
            },
            */

            "static-where": {

                init: function(){

                    flexsearch_static = new FlexSearch({
                        preset: "fast",
                        doc:{
                            id: "id",
                            field: "title"
                        }
                    });
                },
                add: function(content){

                    flexsearch_static.add(content);
                },
                query: function(query){

                    return flexsearch_static.where({

                        genre: "Adventure"
                    });
                },
                loops: 400
            },

            "static-where-tag": {

                init: function(){

                    flexsearch_static_tag = new FlexSearch({
                        preset: "fast",
                        doc:{
                            id: "id",
                            field: "title",
                            tag: "genre"
                        }
                    });
                },
                add: function(content){

                    flexsearch_static_tag.add(content);
                },
                query: function(query){

                    return flexsearch_static_tag.where({

                        genre: "Adventure"
                    });
                },
                loops: 5000000
            },

            "static-where-query": {

                init: function(){

                    flexsearch_static_query = new FlexSearch({
                        preset: "fast",
                        doc:{
                            id: "id",
                            field: "title"
                        }
                    });
                },
                add: function(content){

                    flexsearch_static_query.add(content);
                },
                query: function(query){

                    return flexsearch_static_query.where({

                        title: query,
                        genre: "Adventure"
                    });
                },
                loops: 400
            },

            "static-where-tag-query": {

                init: function(){

                    flexsearch_static_tag_query = new FlexSearch({
                        preset: "fast",
                        doc:{
                            id: "id",
                            field: "title",
                            tag: "genre"
                        }
                    });
                },
                add: function(content){

                    flexsearch_static_tag_query.add(content);
                },
                query: function(query){

                    return flexsearch_static_tag_query.where({

                        title: query,
                        genre: "Adventure"
                    });
                },
                loops: 5000
            },

            "static-find-id": {

                init: function(){

                    flexsearch_find = new FlexSearch({
                        preset: "fast",
                        doc:{
                            id: "id",
                            field: "title"
                        }
                    });
                },
                add: function(content){

                    flexsearch_find.add(content);
                },
                query: function(query){

                    return flexsearch_find.find(10000);
                },
                loops: 20000000
            }
        };

        function init_container(target){

            var html = "<table>" +
                       "<tr>" +
                            "<th>Preset&emsp;</th>" +
                            "<th>Single Phrase&emsp;</th>" +
                            "<th>Multi Phrase&emsp;</th>" +
                            "<th>Not Found&emsp;</th>" +
                       "</tr>";

            for(var test in tests){

                if(tests.hasOwnProperty(test)){

                    html += "<tr>" +
                                "<td>" + test + "</td>" +
                                "<td id=\"test-" + test + "\">indexing ...</td>" +
                                "<td id=\"test-multi-" + test + "\"></td>" +
                                "<td id=\"test-notfound-" + test + "\"></td>" +
                            "</tr>"
                }
            }

            html += "</table>";

            target.innerHTML = html;
        }

        var is_mobile =  navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/);
        var genres = ["Comedy", "Adventure", "Comic", "Horror"];

        function init_tests(index, keys){

            var key = keys[index];
            var test = tests[key];

            test.init();

            if(is_mobile && (test.loops > 1)){

                test.loops = (test.loops / 5) >> 0;
            }

            for(var i = 0; i < data.length; i++){

                test.add({
                    id: i,
                    genre: genres[i % 4],
                    title: data[i]
                });
            }

            document.getElementById("test-" + key).textContent = "ready ...";

            if(++index < keys.length){

                setTimeout(function(){

                    init_tests(index, keys);

                }, 100);
            }
            else{

                setTimeout(function(){

                    start_tests(0, 0, keys);

                }, 1000);
            }
        }

        function start_tests(suite, index, keys){

            var phrase = suite === 0 ? "mermaid" : (suite === 1 ? "little mermaid" : "undefined");
            var key = keys[index];
            var test = tests[key];
            var loops = test.loops;
            var query = test.query;
            var start = Date.now();

            for(var x = 0; x < loops; x++){

                query(phrase);
            }

            var duration = Date.now() - start;

            console.log("[Suite " + suite + "] " + key + ":", duration);

            document.getElementById("test-" + (suite === 1 ? "multi-" : (suite === 2 ? "notfound-" : "")) + key).textContent = format_number(((1000 / duration * loops * 10 + 0.5) >> 0) / 10) + " op/s";

            if(++index >= keys.length){

                if(++suite < 3){

                    index = 0;
                }
            }

            if(index < keys.length){

                setTimeout(function(){

                    start_tests(suite, index, keys);

                }, 1000);
            }
        }

        init_container(document.getElementById("container"));

        setTimeout(function(){

            init_tests(0, Object.keys(tests));

        }, 100);

        function format_number(num){

            return ("" + num).replace(/(\d)(?=(\d{3})+\b)/g, '$1,');
        }

        // ---------------------------------------

        //window.tests = tests;
    })();
</script>
</body>
</html>
